#include <muduo/net/EventLoop.h>
#include <muduo/net/TcpClient.h>
#include <muduo/net/TcpServer.h>
#include <muduo/base/Timestamp.h>
#include <iostream>
#include <string>
#include <functional>

// using namespace muduo;
// using namespace muduo::net;
using namespace std::placeholders;
// testmuduo有三个基本的成员   TcpServer TcpClinet  EventLoop TcpConnection
const std::string ServerName = "server of chat";

class ChatServer
{
public:
    ChatServer(muduo::net::EventLoop *eventLoop,
               const muduo::net::InetAddress listenAddr,
               const std::string name = ServerName)
        : _eventLoop(eventLoop),
          _tcpServer(eventLoop, listenAddr, name)
    {
        // 注册负责用户链接和删除的回调方法，
        _tcpServer.setConnectionCallback(std::bind(&ChatServer::onConnection, this, _1));

        // 注册负责用户读写的事件的回调方法
        _tcpServer.setMessageCallback(std::bind(&ChatServer::onMessage, this, _1, _2, _3));
        // 我的电脑是cpu有12个核心处理器，故这里设置为12个线程（由负责读写事件的线程和负责IO的线程组成）
        _tcpServer.setThreadNum(12);
    }

    void Start()
    {_tcpServer.start();}

   

private:
    // 把链接的处理注册到muduo库上，不要管什么时候调用 epoll listenfd accpet
    void onConnection(const muduo::net::TcpConnectionPtr &tcpConnectionPtr)
    {
        //关于这段逻辑我觉得应该写成一个日志，到时候开发logMessage系统
        if(tcpConnectionPtr->connected())
        {
            std::cout << "The ip port is :" << tcpConnectionPtr->peerAddress().toIpPort() << "sucessed connect to " 
            << tcpConnectionPtr->localAddress().toIpPort() <<std::endl;
        }
        else
        {
              std::cout << "warning : The ip port is :" << tcpConnectionPtr->peerAddress().toIpPort() << "failed connect to " 
            << tcpConnectionPtr->localAddress().toIpPort() << std::endl;

            tcpConnectionPtr->shutdown(); // 相当于 close(socketfd) 释放该资源，结束对其的任务
            //_eventLoop->quit();            // 释放事件循环对象，关闭服务器
        }

    }

    void onMessage(const muduo::net::TcpConnectionPtr &tcpConnectionPtr,
                   muduo::net::Buffer *buffer,
                   muduo::Timestamp time)
    {
         std::string meg = buffer->retrieveAllAsString();

         std::cout << "recvice message come from: " << tcpConnectionPtr->peerAddress().toIpPort() << "include : " 
         << meg << "time : " << time.toFormattedString() << std::endl;

         std::string sendMessage = tcpConnectionPtr->peerAddress().toIpPort();
         sendMessage += " I have received your message : ";
         sendMessage += meg;

         tcpConnectionPtr->send(sendMessage);
    }

private:
    muduo::net::TcpServer _tcpServer;
    muduo::net::EventLoop *_eventLoop;
};

int  main()
{
    muduo::net::EventLoop _eventloop;
    muduo::net::InetAddress ipPort("127.0.0.1",8888);
    ChatServer chatServer(&_eventloop,ipPort,ServerName);

    chatServer.Start(); // _tcpServer进入监听状态
    _eventloop.loop(); // 事件循环开始阻塞式等待事件发生，然后立即派发给线程处理

    return 0;
}

